using System;
using System.Collections.Generic;
using System.Text;

namespace DatabaseCode.Data
{
  // Headers は C++ コード上は複数のヘッダファイルを指す。

  /*
   * パースする文字列の例：
//@MonDataMgr //クラス名

//払出
struct LotNo {
  int code;          // ★ ロットNoコード
  char no[kTextSize];// ロットNo
  int item_code;     // 品名コード ●Item.code

  bool IsEqualKey(const LotNo& r) { return r.code == code; }
};
   */
  class D1_Headers
  {
    //str は複数の複数のヘッダファイル内の構造体（テーブル）一覧文字列である。
    //　各ヘッダファイルは最初にMgrを除く //@ManagerName という形式でマネージャ名を指定しなければならない。
    public D1_Headers(string str)
    {
      m_headers = new List<D2_Header>();
      StringBuilder sb = new StringBuilder();
      string managerName;
      string dataHeader;
      int i = 0;

      //最初の @ を探す
      if (Utility.Skip(str, ref i, '@'))
        return;

      for (;i < str.Length; i++)
      {
        //マネージャ名を読み込む
        managerName = "";
        for (; i < str.Length; i++)
        {
          if (Utility.IsLetterOrDigitOrUnderscore(str[i]))
          {
            managerName += str[i];
          }
          else
          {
            break;
          }
        }
        dataHeader = Utility.SeparateByUndercores(managerName) + ".h";
        managerName += "Mgr";
        Utility.SkipLine(str, ref i);

        //本体をコピー
        sb.Length = 0;
        for (; i < str.Length; i++)
        {
          if (str[i] == '@')
          {
            break;
          }
          sb.Append(str[i]);
        }

        //本体読み込み
        m_headers.Add(new D2_Header(sb.ToString(), managerName, dataHeader));
      }
    }

    //findTable の findMember に参照制約があるテーブルを探す。
    // 戻り値：1件以上見つかった場合は true 。
    public bool FindReference(string findTable, string findMember, out List<D_Reference> refs)
    {
      refs = new List<D_Reference>();

      foreach (D2_Header header in m_headers)
      {
        header.FindReference(findTable, findMember, ref refs, header.Membername);
      }
      return refs.Count > 0 ? true : false;
    }

    //戻り値：findHeader に参照されている findHeader を除くヘッダコレクションを返す。
    public HashSet<D2_Header> EnumRequiredHeaders(D2_Header findHeader)
    {
      var list = new HashSet<D2_Header>();
      foreach (D3_Table findTable in findHeader.Tables)
      {
        foreach (D4_Field findField in findTable.Fields)
        {
          foreach (D2_Header h in m_headers)
          {
            if (h.Name != findHeader.Name)
            {
              foreach (D3_Table t in h.Tables)
              {
                if (findField.HasReference && t.Name == findField.RefTable)
                {
                  list.Add(h);
                }
              }
            }
          }
        }
      }
      return list;
    }

    //戻り値：テーブル名（構造体名）から検索したヘッダー名
    public string GetHeaderName(string tablename)
    {
      foreach (D2_Header h in m_headers)
      {
        foreach (D3_Table t in h.Tables)
        {
          if (t.Name == tablename)
          {
            return h.Name;
          }
        }
      }
      Debug.AddMessageLine("D1_Headers.GetHeaderName ヘッダー名（マネージャ名）が見つかりません.");
      Debug.AddMessageLine("tablename(テーブル名)=" + tablename + "\r\n");
      return "";
    }

    //戻り値：マネージャパラメータ用文字列を返す。
    //例：MonDataMgr* mon_data_mgr, MgrDataMgr* mgr_data_mgr
    public string GetManagerParameterString()
    {
      string str = "";
      bool is_first = true;
      foreach (D2_Header h in this.m_headers)
      {
        if (is_first)
        {
          is_first = false;
        }
        else
        {
          str += ", ";
        }
        str += h.Name + "* " + h.Membername;
      }
      return str;
    }

    //テーブルの総数を返す
    public int GetTableNumber()
    {
      int i = 0;
      foreach (D2_Header h in this.m_headers)
      {
        foreach (D3_Table t in h.Tables)
        {
          i++;
        }
      }
      return i;
    }

    //テーブル番号を返す
    public int GetTableNo(string tablename)
    {
      int i = 0;
      foreach (D2_Header h in this.m_headers)
      {
        foreach (D3_Table t in h.Tables)
        {
          if (t.Name == tablename)
          {
            return i;
          }
          i++;
        }
      }
      Debug.AddMessageLine("D1_Headers.cs GetTableNo テーブル番号見つからずorz");
      return 0;
    }

    //テーブル番号に対応するテーブル名を返す
    public string GetTablename(int tableno)
    {
      int i = 0;
      foreach (D2_Header h in this.m_headers)
      {
        foreach (D3_Table t in h.Tables)
        {
          if (i == tableno)
          {
            return t.Name;
          }
          i++;
        }
      }
      Debug.AddMessageLine("D1_Headers.cs GetTablename テーブル番号見つからずorz");
      return "";
    }

    public List<D2_Header> Headers
    {
      get
      {
        return m_headers;
      }
    }

    private List<D2_Header> m_headers;
  }
}
